﻿//-----------------------------------------------------------------------
// <copyright file="WordsBaseUnitTests.cs" company="Anurag Chatterjee">
//     Copyright (c) Anurag Chatterjee. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace WordsBaseTest
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using Microsoft.QualityTools.Testing.Fakes;   
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using WordsBase;

    /// <summary>
    /// The words base unit tests.
    /// </summary>
    [TestClass]
    public class WordsBaseUnitTests
    {
        /// <summary>
        /// Adds the word to derived list should return true for valid parameters.
        /// </summary>
        [TestMethod]
        public void AddWordToDerivedListShouldReturnTrueForValidParameters()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.AddWordToRootInSourceXmlStringString =
                    (xmlFileProcessorParameter, x, y) => true;
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                var result = xmlFileProcessor.AddWordToDerivedList("Water", "Jal");
                Assert.IsTrue(result);
            }
        }

        /// <summary>
        /// Adds the word to derived list should return false for existing parameters.
        /// </summary>
        [TestMethod]
        public void AddWordToDerivedListShouldReturnFalseForExistingParameters()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.AddWordToRootInSourceXmlStringString =
                    (xmlFileProcessorParameter, x, y) => true;
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                var result = xmlFileProcessor.AddWordToDerivedList("Water", "Pani");
                Assert.IsFalse(result);
            }
        }

        /// <summary>
        /// Adds the word to derived list should return true when first element is added.
        /// </summary>
        [TestMethod]
        public void AddWordToDerivedListShouldReturnTrueWhenFirstElementIsAdded()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.AddWordToRootInSourceXmlStringString =
                    (xmlFileProcessorParameter, x, y) => true;
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.ParseXmlFile = (xmlFileProcessorParameter) =>
                {
                    var wordsList = new Dictionary<string, string>();
                    return wordsList;
                };
                string fileLocation = "C:\\Documents\\file.xml";
                var xmlFileProcessor = new XmlFileProcessor(fileLocation);
                var result = xmlFileProcessor.AddWordToDerivedList("Water", "Pani");
                Assert.IsTrue(result);
            }
        }

        /// <summary>
        /// Deletes the word from derived list should return true when an element is deleted.
        /// </summary>
        [TestMethod]
        public void DeleteWordFromDerivedListShouldReturnTrueWhenAnElementIsDeleted()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.DeleteWordFromRootListInSourceXmlStringString =
                    (processor, s, arg3) => true;
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                var result = xmlFileProcessor.DeleteWordFromDerivedList("Water", "Pani");
                Assert.IsTrue(result);
            }
        }

        /// <summary>
        /// Deletes the word from derived list should return false when a non existent element is deleted.
        /// </summary>
        [TestMethod]
        public void DeleteWordFromDerivedListShouldReturnFalseWhenANonExistentDerivedElementIsDeleted()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.DeleteWordFromRootListInSourceXmlStringString =
                    (processor, s, arg3) => true;
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                var result = xmlFileProcessor.DeleteWordFromDerivedList("Water", "Neer");
                Assert.IsFalse(result);
            }
        }

        /// <summary>
        /// Deletes the word from derived list should return false when a non existent root is provided.
        /// </summary>
        [TestMethod]
        public void DeleteWordFromDerivedListShouldReturnFalseWhenANonExistentRootElementIsProvided()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.DeleteWordFromRootListInSourceXmlStringString =
                    (processor, s, arg3) => true;
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                var result = xmlFileProcessor.DeleteWordFromDerivedList("Fire", "Pani");
                Assert.IsFalse(result);
            }
        }

        /// <summary>
        /// Deletes the word from derived list should return true when the only element is deleted.
        /// </summary>
        [TestMethod]
        public void DeleteWordFromDerivedListShouldReturnTrueWhenTheOnlyElementIsDeleted()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.DeleteWordFromRootListInSourceXmlStringString =
                    (processor, s, arg3) => true;
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.ParseXmlFile = (xmlFileProcessorParameter) =>
                {
                    var wordsList = new Dictionary<string, string>();
                    wordsList.Add("Monalisa", "Da Vinci");
                    return wordsList;
                };
                string fileLocation = "C:\\Documents\\file.xml";
                var xmlFileProcessor = new XmlFileProcessor(fileLocation);
                var result = xmlFileProcessor.DeleteWordFromDerivedList("Da Vinci", "Monalisa");
                Assert.IsTrue(result);
            }
        }

        /// <summary>
        /// Gets the word root should return the correct root for a given word.
        /// </summary>
        [TestMethod]
        public void GetWordRootShouldReturnTheCorrectRootForAGivenWord()
        {
            using (ShimsContext.Create())
            {
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                var rootWord = xmlFileProcessor.GetWordRoot("Pani");
                Assert.IsTrue(string.Compare(rootWord.Key, "Water", false, CultureInfo.CurrentCulture) == 0);
            }
        }

        /// <summary>
        /// Gets the word root should return empty string if provided word does not exist.
        /// </summary>
        [TestMethod]
        public void GetWordRootShouldReturnEmptyStringIfProvidedWordDoesNotExist()
        {
            using (ShimsContext.Create())
            {
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                var rootWord = xmlFileProcessor.GetWordRoot("Rani");
                Assert.IsTrue(string.IsNullOrEmpty(rootWord.Key));
            }
        }

        /// <summary>
        /// Gets all words with root should return all words having the given root.
        /// </summary>
        [TestMethod]
        public void GetAllWordsWithRootShouldReturnAllWordsHavingTheGivenRoot()
        {
            using (ShimsContext.Create())
            {
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                var wordsWithSameRoot = xmlFileProcessor.GetAllWordsWithRoot("King");
                Assert.AreEqual(2, wordsWithSameRoot.Count);
            }
        }

        /// <summary>
        /// Gets all words with root should return no words if no word has the provided root.
        /// </summary>
        [TestMethod]
        public void GetAllWordsWithRootShouldReturnNoWordsIfNoWordHasTheProvidedRoot()
        {
            using (ShimsContext.Create())
            {
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                var wordsWithSameRoot = xmlFileProcessor.GetAllWordsWithRoot("Queen");
                Assert.AreEqual(0, wordsWithSameRoot.Count);
            }
        }

        /// <summary>
        /// Updates the word in derived list should return true if a word is updated under a root.
        /// </summary>
        [TestMethod]
        public void UpdateWordInDerivedListShouldReturnTrueIfAWordIsUpdatedUnderARoot()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.UpdateWordInXmlSourceStringStringString =
                    (processor, s, arg3, arg4) => true;
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                string oldWord = "Pani";
                string newWord = "Neer";
                string root = "Water";
                var result = xmlFileProcessor.UpdateWordInDerivedList(root, oldWord, newWord);
                Assert.IsTrue(result);
                var rootWord = xmlFileProcessor.GetWordRoot(newWord);
                Assert.AreEqual(root, rootWord.Key);
            }
        }

        /// <summary>
        /// Updates the word in derived list should return false if the new value and old value are same.
        /// </summary>
        [TestMethod]
        public void UpdateWordInDerivedListShouldReturnFalseIfTheNewValueAndOldValueAreSame()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.UpdateWordInXmlSourceStringStringString =
                    (processor, s, arg3, arg4) => true;
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                string oldWord = "Pani";
                string newWord = "Pani";
                string root = "Water";
                var result = xmlFileProcessor.UpdateWordInDerivedList(root, oldWord, newWord);
                Assert.IsFalse(result);
            }
        }

        /// <summary>
        /// Updates the word in derived list should return false if the existing word does not exist.
        /// </summary>
        [TestMethod]
        public void UpdateWordInDerivedListShouldReturnFalseIfTheExistingWordDoesNotExist()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.UpdateWordInXmlSourceStringStringString =
                    (processor, s, arg3, arg4) => true;
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                string oldWord = "Jal";
                string newWord = "Neer";
                string root = "Water";
                var result = xmlFileProcessor.UpdateWordInDerivedList(root, oldWord, newWord);
                Assert.IsFalse(result);
            }
        }

        /// <summary>
        /// Updates the word in derived list should return false if the root word does not exist.
        /// </summary>
        [TestMethod]
        public void UpdateWordInDerivedListShouldReturnFalseIfTheRootWordDoesNotExist()
        {
            using (ShimsContext.Create())
            {
                WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.UpdateWordInXmlSourceStringStringString =
                    (processor, s, arg3, arg4) => true;
                var xmlFileProcessor = this.GetXmlFileProcessorObject();
                string oldWord = "Pani";
                string newWord = "Neer";
                string root = "Fire";
                var result = xmlFileProcessor.UpdateWordInDerivedList(root, oldWord, newWord);
                Assert.IsFalse(result);
            }
        }

        /// <summary>
        /// Gets the XML file processor object.
        /// </summary>
        /// <returns>The XML file processor object.</returns>
        private XmlFileProcessor GetXmlFileProcessorObject()
        {
            WordsBase.Fakes.ShimXmlFileProcessor.AllInstances.ParseXmlFile = (xmlFileProcessorParameter) =>
                {
                    var wordsList = new Dictionary<string, string>();
                    wordsList.Add("Shah", "King");
                    wordsList.Add("Raja", "King");
                    wordsList.Add("Pani", "Water");
                    return wordsList;
                };
            string fileLocation = "C:\\Documents\\file.xml";
            var xmlFileProcessor = new XmlFileProcessor(fileLocation);
            return xmlFileProcessor;
        }
    }
}
